#ifndef RANDOM_H
#define RANDOM_H
#include "globals.h"
#include "math/random.h"
namespace gemren
{
	
	class random : protected embree::Random
	{
		int current;
		void perpendiculars(const coord& normal, coord& dx, coord& dy) //creates base of normal
		{
			if(abs(normal.x) < EPSILON && abs(normal.y) < EPSILON )
			{
				dx = coord(1,0,0);
			}
			else
			{
				// equiv to cross(coord(0,0,1), normal));
				dx = embree::normalize(coord(-normal.y,normal.x,0)) ;
			}
			dy = (embree::cross(normal, dx));
		}
	public:
		random(int seed): embree::Random(seed){}
		inline int get()
		{
			return this->getInt();
			
		}
		inline float getf()
		{
			return getFloat();
		}
		coord uniform_hemisphere(const coord& normal)
		{
			
			float sin_lat = (2*getf()-1);
			float len = getf()*2*float(embree::pi);
			coord ret(embree::cos(len)*sin_lat, embree::sin(len)*sin_lat, /* cos lat =*/embree::sqrt(1-sin_lat*sin_lat));
			return embree::dot(normal, ret) > 0? ret: -ret;
		}
		coord cosined_hemisphere(const coord& normal)
		{
			coord dx, dy;
			perpendiculars(normal, dx, dy);
			
			float lon = getf() * 2*3.141592654f;
			
			float r = getf();
			float cosfi = sqrt(r), sinfi = sqrt(1-r);
			coord loc( sinfi*cos(lon), sinfi*sin(lon), cosfi);
			coord ret(
				    loc.x * dx + loc.y*dy+loc.z*normal
				);
			return ret;
		}
		coord normal_dist(const coord& normal, const float var)
		{
			float u1 = getf(), u2 = getf()*2*3.141592654f;
			float r = var * sqrt(-2.0f*log(u1)); //as in box-muller

			float sinfi( sin(3.141592654f*0.5f*r));
			coord loc( sinfi*cos(u2), sinfi*sin(u2), sqrt(1-sinfi*sinfi));

			
			coord dx, dy;
			perpendiculars(normal, dx, dy);
			
			return coord(
				    loc.x * dx + loc.y*dy+loc.z*normal
				);
		}
		coord cosn_lobe(const coord& normal, const float n)
		{
			coord dx, dy;
			perpendiculars(normal, dx, dy);
			
			float lon = getf() * 2*3.141592654f;
			
			float r = getf();
			float cosfi = pow(r, 1.0f/(n+1.0f));
			float sinfi = sqrt(1- cosfi*cosfi);
			
			coord loc( sinfi*cos(lon), sinfi*sin(lon), cosfi);
			
			coord ret(
				    loc.x * dx + loc.y*dy+loc.z*normal
				);
			return ret;
		}

		coord2d uniform_triangle()
		{
			float u = getf(), v = getf();
			return u+v <=1 ? coord2d(u,v) : coord2d(1-u, 1-v);
		}
	};
}

#endif 